﻿using CommonModel.Field;
using GXRTBTC.PublicClassLibrary.Field;
using GXRTBTC.PublicClassLibrary.Util;
using Microsoft.Extensions.Logging;
using NewLife.Log;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using static CommonModel.Model.DataTypeDll;

namespace CommonModel.Util
{
    public class StructUtil
    {
        /// <summary>
        /// 结构体解析
        /// </summary>
        /// <param name="doc">配置</param>
        /// <param name="data">数据</param>
        /// <param name="bodybegin">起始字节</param>
        /// <returns></returns>
        public static Dictionary<string, object> ByteParseViaStruct(SchemaDocument doc, byte[] data,int bodybegin)
        {
            int currentCursor = bodybegin; // data字节数组解析游标起始位置
            int currentParsedIndex = 0; // 解析后字段的顺序
            Dictionary<int, SchemaDictionary> schemaDictionary = doc.fieldDictionary;//读取的XML模板的字段字典

            //解析后的字典
            Dictionary<string, object> parsedDataDictionary = new Dictionary<string, object>();
            parseDictionary(schemaDictionary, parsedDataDictionary, data, ref currentCursor, ref currentParsedIndex);
            return parsedDataDictionary;
        }

        /// <summary>
        /// 解析函数
        /// </summary>
        /// <param name="schemaDictionary"></param>
        /// <param name="parsedDataDictionary"></param>
        /// <param name="data"></param>
        /// <param name="currentCursor"></param>
        /// <param name="currentParsedIndex"></param>
        public static void parseDictionary(Dictionary<int, SchemaDictionary> schemaDictionary, Dictionary<string, object> parsedDataDictionary, byte[] data, ref int currentCursor, ref int currentParsedIndex)
        {
            //根据配置文件循环
            for (int i = 0; i < schemaDictionary.Count; i++) 
            {
                SchemaDictionary schema = schemaDictionary[i];

                //如果是普通字段，且字节位标识bit字段
                if (!schema.isNode)
                {
                    string pname = schema.name;//当前解析到的字段的名字            
                    DataType type = schema.type;
                    int size = schema.size;
                    try
                    {
                        //长度超出则中断操作
                        if (currentCursor + size > data.Length)
                        {
                            continue;
                        }

                        byte[] datax = new byte[size];

                        //使用字段的长度作为待解析的数据
                        Array.Copy(data, currentCursor, datax, 0, size);//将data字节数组所需解析的当前字段复制过来
                        currentCursor = currentCursor + size;//字节数组游标移动
                        currentParsedIndex++;//移动游标
                        string value = BytesParseToTypeString.ParseValue(type, datax);// 开始解析
                        parsedDataDictionary.Add(pname, value);
                    }
                    catch (Exception e)
                    {
                        CommonUtil.mLogger.LogError("Struct.parseDictionary函数解析字段 " + i + " 名称: " + pname + " type: " + type + " 失败!\n" + e);
                    }
                }
                //如果是字段集
                else
                {
                    DataType datype = schema.type;
                    string pname = schema.name;
                    int looper;
                    parsedDataDictionary.TryAdd(pname, new List<Dictionary<string, object>>());
                    switch (datype)
                    {
                        //位状态结构体, 低位在前高位在后
                        case DataType.BITARRAY:
                            looper = getLooper(schema, parsedDataDictionary);//获取到循环次数
                            for (int counter = 0; counter < looper; counter++)
                            {
                                try
                                {
                                    parseBitArray(schema, (List<Dictionary<string, object>>)parsedDataDictionary[pname], data, ref currentCursor, ref currentParsedIndex);//解析好的子集
                                }
                                catch(Exception e)
                                {
                                    CommonUtil.mLogger.LogError("Struct.parseDictionary函数解析字段 " + i + " 名称: " + pname + " 失败!\n" + e);
                                }
                            }
                            break;

                        //结构体类型
                        case DataType.STRUCT:
                            looper = getLooper(schema, parsedDataDictionary);//获取到循环次数
                            if (looper == -1)//不解析，进行下一个字段解析
                            {
                                break;
                            }

                            //子配置
                            Dictionary<int, SchemaDictionary> subSchFieldDictionary = schema.fieldDictionary;

                            //嵌套循环解析
                            for (int counter = 0; counter < looper; counter++)
                            {
                                ((List<Dictionary<string, object>>)(parsedDataDictionary)[pname]).Add(new Dictionary<string, object>());
                                try
                                {
                                    parseDictionary(subSchFieldDictionary, ((List<Dictionary<string, object>>)(parsedDataDictionary)[pname])[counter], data, ref currentCursor, ref currentParsedIndex);//把list传入，有loop的字段放list中存放
                                }
                                catch(Exception e)
                                {
                                    CommonUtil.mLogger.LogError("Struct.parseDictionary函数解析字段 " + i + " 名称: " + pname + " 失败!\n" + e);
                                }
                            }

                            break;
                        default:
                            break;
                    }
                }
            }
        }

        /// <summary>
        /// 获取结构体数组的长度
        /// </summary>
        /// <param name="subSchDictionary">结构体解析字典</param>
        /// <param name="parsedDataDictionary">解析好的字典</param>
        /// <returns>字典中实际的loop属性值, 即数组个数</returns>
        public static int getLooper(SchemaDictionary subSchDictionary, Dictionary<string, object> parsedDataDictionary)
        {
            string loopStr = subSchDictionary.loop;
            if (loopStr == "0")
            {
                return -1;//表示不解析该字段
            }

            string loopValueStr;
            int loop = 1;

            if (null == loopStr || loopStr.Equals(""))
            {
                loopStr = "1";
            }

            //正则判断是否是数字
            string regex = "^(-?[0-9]*[.]*[0-9]{0,3})$";
            /**
             * 如果是关联字段获取数组个数
             */
            if (Regex.IsMatch(loopStr, regex))
            {
                loopValueStr = loopStr;
                loop = Convert.ToInt32(loopValueStr);  
            }
            else
            {
                if (parsedDataDictionary.ContainsKey(loopStr))
                {
                    // 从已经解析的parsedDataDictionary中取出对应的值
                    loopValueStr = parsedDataDictionary[loopStr].ToString();
                    loop = Convert.ToInt32(loopValueStr);
                }
                else
                {
                    bool match = false;
                    //typeof(List<>).Name
                    foreach (string key in parsedDataDictionary.Keys)
                    {
                        if (parsedDataDictionary[key] != null && parsedDataDictionary[key].GetType().Name.Equals(typeof(List<>).Name))
                        {
                            List<Dictionary<string, object>> listVal = (List<Dictionary<string, object>>)parsedDataDictionary[key];
                            foreach (Dictionary<string, object> dictVal in listVal)
                            {
                                if (dictVal.ContainsKey(loopStr))
                                {
                                    //从已经解析的parsedDataDictionary中取出对应的值
                                    loopValueStr = dictVal[loopStr].ToString();
                                    loop = Convert.ToInt32(loopValueStr);
                                    match = true;
                                    break;
                                }
                            }
                        }
                        if (match)
                        {
                            break;
                        }
                    }
                }
            }
            return loop;
        }

        /// <summary>
        /// 解析成字节位结构体
        /// </summary>
        /// <param name="subSchDictionary"></param>
        /// <param name="parsedDataDictionary"></param>
        /// <param name="data"></param>
        /// <param name="currentCursor"></param>
        /// <param name="currentParsedIndex"></param>
        public static void parseBitArray(SchemaDictionary subSchDictionary, List<Dictionary<string, object>> parsedDataDictionary, byte[] data, ref int currentCursor, ref int currentParsedIndex)
        {
            int dataSize = subSchDictionary.size;

            //长度超出则中断操作
            if (currentCursor + dataSize > data.Length)
            {
                return;
            }

            //使用字段的长度作为待解析的数据<br/>
            byte[] datax = new byte[dataSize];
            
            //使用字段的长度作为待解析的数据
            Array.Copy(data, currentCursor, datax, 0, dataSize);//将data字节数组所需解析的当前字段复制过来
            currentCursor = currentCursor + dataSize; // 游标前移该字段的字节长度
            currentParsedIndex++;//移动已解析的数据游标
            Dictionary<string, object> subParseDictionary = parseBitArrayMap(subSchDictionary, datax);//开始解析子字段集,subParseDictionary是解析好的子字段集      
            parsedDataDictionary.Add(subParseDictionary);

        }

        /// <summary>
        /// 解析子字段集
        /// </summary>
        /// <param name="subSchDictionary"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Dictionary<string, object> parseBitArrayMap(SchemaDictionary subSchDictionary, byte[] data)
        {
            //byte数组转换为一个长度为8*N的byte数组
            byte[] bitArray = TransForm.bytesToBitArray(data);


            Dictionary<int, SchemaDictionary> schFieldDictionary = subSchDictionary.fieldDictionary;
            Dictionary<string, object> parsedDataDictionary_child = new Dictionary<string, object>();
            for (int i = 0; i < schFieldDictionary.ToArray().Length; i++)
            {
                SchemaDictionary fieldSch = schFieldDictionary[i];
                DataType typechild = fieldSch.type;
                if (i < bitArray.Length)
                {
                    byte[] datax = new byte[1];
                    datax[0] = bitArray[i];
                    string value = "";
                    try
                    {
                        value = BytesParseToTypeString.ParseValue(typechild, datax);
                    }
                    catch (Exception e)
                    {
                        CommonUtil.mLogger.LogError("parseBitArray函数解析字段失败： "+ fieldSch.name + ", 出错信息:\n" + e);
                    }
                    parsedDataDictionary_child.Add(fieldSch.name, value);//只要值不要对象
                }
            }
            return parsedDataDictionary_child;
        }
    }
}
